package org.shj.book1.filesize;

import java.io.File;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class ConcurrentTotalSizeWLatch {
	
	private ExecutorService service;
	private AtomicLong totalSize = new AtomicLong();
    private AtomicLong pendingFiles = new AtomicLong();	
    private CountDownLatch latch = new CountDownLatch(1);

	private void updateTotalSizeOfFilesInDir(File file){
		long fileSize = 0 ;
		if(file.isFile())
			fileSize = file.length();
		else{
			File[] children = file.listFiles();
			if(children  != null){
				for(final File child : children){
					if(child.isFile())
						fileSize += child.length();
					else{
						pendingFiles.incrementAndGet();
						service.execute(new Runnable(){
							public void run(){
								updateTotalSizeOfFilesInDir(child);
							}
						});
					}
				}
			}
		}
		totalSize.addAndGet(fileSize);
		if(pendingFiles.decrementAndGet() == 0)
			latch.countDown();
		
	}
	
	public long getTotalSizeOfFile(final String fileName) throws Exception{
		service = Executors.newFixedThreadPool(100);
		pendingFiles.incrementAndGet();
		try{
			updateTotalSizeOfFilesInDir(new File(fileName));
			latch.await(100, TimeUnit.SECONDS);
			
			return totalSize.longValue();
		}finally{
			service.shutdown();
		}
	}
	
	public static void main(String[] args)throws Exception{
		long start = System.nanoTime();
		String fileName = "D:\\mavenrepos\\repository\\org";
		long total = new ConcurrentTotalSizeWLatch().getTotalSizeOfFile(fileName);
		long end = System.nanoTime();
		
		System.out.println("Total size: " + total);
		System.out.println("Time taken: " + (end - start)/1.0e9);
	}
}

